<!DOCTYPE html>
<html lang="en">
<head>
  <title>Service Workers</title>
  <meta http-equiv="Content-Type" content="text/html;charset=utf-8">
  <script
    src="assets/web-spec-framework/bower_components/platform/platform.js">
  </script>
  <link rel="import"
      href="assets/web-spec-framework/framework.html"/>
  <link rel="stylesheet" href="https://www.w3.org/StyleSheets/TR/W3C-WD" type="text/css">
  <!--
  <link rel="stylesheet" href="../assets/styles/spec.css" type="text/css">
  <link rel="stylesheet" href="../assets/styles/prettify.css" type="text/css">
  <link rel="stylesheet" href="../assets/styles/third_party/W3C-ED.css" type="text/css" >
  <script src="../assets/scripts/bug-assist.js"></script>
  <script src="../assets/scripts/spec-assist.js"></script>
  <script src="../assets/scripts/prettify.js"></script>
  -->
  <!-- <meta name="bug.blocked" content="14968"> -->
  <meta name="bug.short_desc" content="[ServiceWorker]: ">
  <meta name="bug.product" content="WebAppsWG">
  <meta name="bug.component" content="ServiceWorker">
</head>
<body>

<div class="head">
  <div class="logo">
    <a href="//www.w3.org/"><img width="72" height="48" src="//www.w3.org/Icons/w3c_home" alt="W3C"></a>
  </div>

  <h1>Service Workers</h1>
  <h2 id="working-draft">W3C First Public Working Draft 01 May 2014</h2>
  <dl>
  <dt>This version</dt>
    <dd><a href="http://www.w3.org/TR/2014/WD-service-workers-20140501/">http://www.w3.org/TR/2014/WD-service-workers-20140501/</a></dd>
  <dt>Latest version</dt>
    <dd><a href="http://www.w3.org/TR/service-workers/">http://www.w3.org/TR/service-workers/</a></dd>
  <dt>Latest editor's draft</dt>
    <dd><a href="https://slightlyoff.github.io/ServiceWorker/spec/service_worker/">https://slightlyoff.github.io/ServiceWorker/spec/service_worker/</a></dd>
  <dt>Revision history</dt>
    <dd><a id="log" href="https://github.com/slightlyoff/ServiceWorker/commits/master">https://github.com/slightlyoff/ServiceWorker/commits/master</a></dd>
  <dt>Participate</dt>
    <dd>Discuss on <a href="http://lists.w3.org/Archives/Public/public-webapps/">public-webapps@w3.org</a> (<a href="http://www.w3.org/2008/webapps/">Web Applications Working Group</a>)</dd>
    <dd><a href="https://github.com/slightlyoff/ServiceWorker/issues">File bugs</a></dd>
  <dt>Editors</dt>
    <dd class="vcard"><span class="fn">Alex Russell</span>, <span class="org">Google</span>, &lt;<a class="email" href="mailto:slightlyoff@chromium.org">slightlyoff@chromium.org</a>&gt;</dd>
    <dd class="vcard"><span class="fn">Jungkee Song</span>, <span class="org">Samsung Electronics</span>, &lt;<a class="email" href="mailto:slightlyoff@chromium.org">jungkee.song@samsung.com</a>&gt;</dd>
  </dl>

  <p class="copyright"><a href="http://www.w3.org/Consortium/Legal/ipr-notice#Copyright">Copyright</a> © 2014 <a href="http://www.w3.org/"><acronym title="World Wide Web Consortium">W3C</acronym></a><sup>®</sup> (<a href="http://www.csail.mit.edu/"><acronym title="Massachusetts Institute of Technology">MIT</acronym></a>, <a href="http://www.ercim.eu/"><acronym title="European Research Consortium for Informatics and Mathematics">ERCIM</acronym></a>, <a href="http://www.keio.ac.jp/">Keio</a>, <a href="http://ev.buaa.edu.cn/">Beihang</a>), All Rights Reserved. W3C <a href="http://www.w3.org/Consortium/Legal/ipr-notice#Legal_Disclaimer">liability</a>, <a href="http://www.w3.org/Consortium/Legal/ipr-notice#W3C_Trademarks">trademark</a> and <a href="http://www.w3.org/Consortium/Legal/copyright-documents">document use</a> rules apply.</p>

  <hr>

  <h2 id="abstract">Abstract</h2>

  <p>This specification describes a method that enables applications to take advantage of persistent background processing, including hooks to enable bootstrapping of web applications while offline.</p>

  <p>The core of this system is an event-driven <a href="http://www.w3.org/TR/workers/">Web Worker</a>, which responds to events dispatched from documents and other sources. A system for managing installation, versions, and upgrades is provided.</p>

  <p>The Service Worker is a generic entry point for event-driven background processing in the Web Platform that is <a href="#extensibility">extensible by other specifications</a>.</p>

  <h2 id="status">Status of This Document</h2>

  <p><em>This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current <abbr title="World Wide Web Consortium">W3C</abbr> publications and the latest revision of this technical report can be found in the <a href="http://www.w3.org/TR/"><abbr title="World Wide Web Consortium">W3C</abbr> technical reports index</a> at http://www.w3.org/TR/.</em></p>

  <p>This document was published by the <a href="http://www.w3.org/2008/webapps/">Web Applications Working Group</a> as a First Public Working Draft. If you wish to make comments regarding this document, please send them to <a href="mailto:public-webapps@w3.org">public-webapps@w3.org</a> (<a href="mailto:public-webapps-request@w3.org?subject=subscribe">subscribe</a>, <a href="http://lists.w3.org/Archives/Public/public-webapps/">archives</a>). All feedback is welcome.</p><p>Publication as a First Public Working Draft does not imply endorsement by the <abbr title="World Wide Web Consortium">W3C</abbr> Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.</p>

  <p>This document was produced by a group operating under the <a href="http://www.w3.org/Consortium/Patent-Policy-20040205/">5 February 2004 <abbr title="World Wide Web Consortium">W3C</abbr> Patent Policy</a>. <abbr title="World Wide Web Consortium">W3C</abbr> maintains a <a href="http://www.w3.org/2004/01/pp-impl/42538/status" rel="disclosure">public list of any patent disclosures</a> made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains <a href="http://www.w3.org/Consortium/Patent-Policy-20040205/#def-essential">Essential Claim(s)</a> must disclose the information in accordance with <a href="http://www.w3.org/Consortium/Patent-Policy-20040205/#sec-Disclosure">section 6 of the <abbr title="World Wide Web Consortium">W3C</abbr> Patent Policy</a>.</p>
</div>

<spec-toc></spec-toc>

<spec-clause id="introduction">
  <h1 id="h1-introduction">Introduction</h1>

  <spec-section id="about">
    <h1 id="h1-about">About this Document</h1>

    <p>All diagrams, examples, notes, are non-normative, as well as sections explicitly marked as non-normative. Everything else in this specification is normative.</p>

    <p>The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in the normative parts of this document are to be interpreted as described in <a href="http://dev.w3.org/2006/xbl2/#refsRFC2119">RFC2119</a>. For readability, these words do not appear in all uppercase letters in this specification.</p>

    <p>Any point, at which a conforming UA must make decisions about the state or reaction to the state of the conceptual model, is captured as <a href="http://en.wikipedia.org/wiki/Algorithm">algorithm</a>. The algorithms are defined in terms of processing equivalence. The <dfn id="dfn-processing-equivalence">processing equivalence</dfn> is a constraint imposed on the algorithm implementors, requiring the output of the both UA-implemented and the specified algorithm to be exactly the same for all inputs.</p>
  </spec-section>

  <spec-section id="dependencies">
    <h1 id="h1-dependencies">Dependencies</h1>

    <p>This document relies on the following specifications:</p>

    <ul>
      <li><a href="http://www.w3.org/TR/workers/">Web Workers</a></li>
      <li><a href="http://fetch.spec.whatwg.org/">Fetch Living Standard</a></li>
      <li><a href="http://dom.spec.whatwg.org/">DOM Living Standard</a></li>
      <li><a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/">HTML Living Standard</a></li>
      <li><a href="http://ecma-international.org/ecma-262/5.1/">ECMAScript Language Specification</a></li>
      <li><a href="http://www.w3.org/TR/WebIDL/">Web IDL</a></li>
      <li><a href="http://www.w3.org/TR/IndexedDB/">Indexed DB</a></li>
      <li><a href="http://www.w3.org/TR/quota-api/">Quota Management API</a></li>
      <li><a href="http://www.w3.org/TR/notifications/">Web Notifications</a></li>
      <li><a href="http://tools.ietf.org/html/rfc6454">The Web Origin Concept</a></li>
    </ul>
  </spec-section>

  <spec-section class="informative" id="motivations">
    <h1 id="h1-motivations">Motivations</h1>

    <p>Web Applications traditionally assume that the network is reachable. This assumption pervades the platform. HTML documents are loaded over HTTP and traditionally fetch all of their sub-resources via subsequent HTTP requests. This places web content at a disadvantage versus other technology stacks.</p>

    <p>The Service Worker is designed first to redress this balance by providing a Web Worker context, which can be started by a runtime when navigations are about to occur. This event-driven worker is registered against an origin and a path (or pattern), meaning it can be consulted when navigations occur to that location. Events that correspond to network requests are dispatched to the worker and the responses generated by the worker may over-ride default network stack behavior. This puts the Service Worker, conceptually, between the network and a document renderer, allowing the Service Worker to provide content for documents, even while offline.</p>

    <p>Web developers familiar with previous attempts to solve the offline problem have reported a deficit of flexibility in those solutions. As a result, the Service Worker is highly procedural, providing a maximum of flexibility at the price of additional complexity for developers. Part of this complexity arises from the need to keep Service Workers responsive in the face of a single-threaded execution model. As a result, APIs exposed by Service Workers are almost entirely asynchronous, a pattern familiar in other JavaScript contexts but accentuated here by the need to avoid blocking document and resource loading.</p>

    <p>Developers using the <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/offline.html">HTML5 Application Cache</a> have also <a href="http://alistapart.com/article/application-cache-is-a-douchebag">reported that several attributes</a> of the design contribute to <a href="http://alistapart.com/article/application-cache-is-a-douchebag#section6">unrecoverable errors</a>. A key design principle of the Service Worker is that errors should <em>always</em> be recoverable. Many details of the update process of Service Workers are designed to avoid these hazards.</p>

    <p>Service Workers are started and kept alive by their relationship to events, not documents. This design borrows heavily from developer and vendor experience with <a href="http://www.w3.org/TR/workers/#sharedworker">Shared Workers</a> and <a href="https://developer.chrome.com/extensions/background_pages">Chrome Background Pages</a>. A key lesson from these systems is the necessity to time-limit the execution of background processing contexts, both to conserve resources and to ensure that background context loss and restart is top-of-mind for developers. As a result, Service Workers bear more than a passing resemblance to <a href="https://developer.chrome.com/extensions/event_pages">Chrome Event Pages</a>, the successor to Background Pages. Service Workers may be started by user agents <em>without an attached document</em> and may be killed by the user agent at nearly any time. Conceptually, Service Workers can be thought of as Shared Workers that can start, process events, and die without ever handling messages from documents. Developers are advised to keep in mind that Service Workers may be started and killed many times a second.</p>

    <p>Service Workers are generic, event-driven, time-limited script contexts that run at an origin. These properties make them natural endpoints for a range of runtime services that may outlive the context of a particular document, e.g. handling push notifications, background data synchronization, responding to resource requests from other origins, or receiving centralized updates to expensive-to-calculate data (e.g., geolocation or gyroscope).</p>
  </spec-section>
</spec-clause>

<spec-clause id="concepts">
  <h1 id="h1-concepts">Concepts</h1>

  <p>A <dfn id="service-worker">Service Worker</dfn> is a type of <a href="http://www.w3.org/TR/workers/">Web Worker</a>. Unlike other types of Web Worker, the lifetime of a Service Worker is tied to the execution lifetime of events, not references held by documents to the <a href="#service-worker-obj">worker object</a>. In practice, this means that <a href="#service-worker">Service Workers</a> may begin, end, and restart execution many times over the life of documents which they logically <a href="#document-control">control</a>.</p>

  <p>Service Workers are <a href="#installation-algorithm">installed</a> by user agents after being <a href="#navigator-service-worker-register">registered</a> by authors from the context of a <a href="http://dom.spec.whatwg.org/#concept-document">document</a>. Service Workers execute in the registering document's <a href="http://goo.gl/58tlSE">origin</a>.</p>

  <p><a href="#registration-algorithm">Registration</a> maps a <a href="#service-worker">Service Worker</a> script to <dfn id="url-scope">url scope</dfn>, a tuple of <a href="http://tools.ietf.org/html/rfc6454">origin</a> and <a href="#path-expression">path expression</a>. User agents may enable many registrations at a single origin so long as the <a href="#path-expression">path expression</a> of the registration differs. <a href="#registration-algorithm">Registration</a> of an identical <a href="http://tools.ietf.org/html/rfc6454">origin</a>/<a href="#path-expression">path expression</a> when one already exists in the user agent causes the existing registration to be replaced.</p>

  <p>A <dfn id="path-expression">path expression</dfn> consists of a <a href="http://url.spec.whatwg.org/#concept-relative-url">relative url</a> which may, optionally, terminate with the charachter <code>"*"</code>. Ending a <a href="#path-expression">path expression</a> with <code>"*"</code> enables <a href="#scope-match-algorithm">longest-prefix wildcard matching</a>.</p>

  <p>A document is "<dfn id="document-control">controlled</dfn>" if an <a href="#navigator-service-worker-current">active</a> <a href="#service-worker">Service Worker</a> <a href="#scope-match-algorithm">matches</a> the document's URL upon <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/history.html#navigate">navigation</a>. Multiple documents may be concurrently <a href="#document-control">controlled</a> by a single <a href="#service-worker">Service Worker</a> instance. That is, <a href="#service-worker">Service Workers</a> have a one-to-many relationship with <a href="#document-control">controlled</a> documents.</p>

  <p>The <dfn id="lifecycle-events">Lifecycle events</dfn> of Service Workers are <code><a href="#install-event">install</a></code> and <code><a href="#activate-event">activate</a></code>. <dfn id="functional-events">Functional events</dfn> are <a href="http://dom.spec.whatwg.org/#interface-event">DOM Events</a> that are dispatched in the <a href="#service-worker-global-scope">Service Worker global context</a> which are not <a href="#lifecycle-events">lifecycle events</a> of the Service Worker.</p>

  <p>Registered Service Workers do not immediately begin to receive <a href="#functional-events">functional events</a> for documents. Registration is the first step in installation, which proceeds through several phases:</p>

  <ol>
    <li><em>Fetch</em>:
    <br>
    The script URL provided by the author (via a call to <a href="#navigator-service-worker-register"><code>navigator.serviceWorker.register([script URL], [registration option])</code></a> from a document) is fetched without <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.2.2">heuristic caching</a>. If the return status code of the fetch is not <a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.2">2xx</a>, installation aborts.</li>
    <li><em>Startup</em>:
    <br>
    If fetching the worker script is successful, it is <a href="http://www.w3.org/TR/workers/#processing-model">executed</a> in a <code><a href="#service-worker-global-scope">ServiceWorkerGlobalScope</a></code>. These scripts may call <code><a href="http://www.w3.org/TR/workers/#importing-scripts-and-libraries">importScripts</a></code> resulting in further fetches. Imported scripts are fetched, <a href="https://people.mozilla.org/~jorendorff/es5.1-final.html#sec-5.1.4">parsed</a> and <a href="https://people.mozilla.org/~jorendorff/es5.1-final.html#sec-10.4.1">executed</a> in turn, per the ECMA-262 and <a href="http://www.w3.org/TR/workers/#importing-scripts-and-libraries">Web Worker specifications</a>. All resources downloaded as part of the very first startup of a Service Worker are cached along with the worker script as described in <a href="#update-algorithm">"Worker Script Caching"<!--TODO(jungkees): add worker script caching section--></a>.
    </li>
    <li><em><code>oninstall</code></em>:
    <br>
    Once a Service Worker has been fetched and started, it is ready to process <a href="http://dom.spec.whatwg.org/#interface-event">events</a>. The first event sent to every Service Worker is <a href="#install-event"><code>install</code></a>. Workers that handle this event are encouraged to use it as a way to prime the available storage mechanisms for supporting offline application use; perhaps by populating <a href="http://www.w3.org/TR/IndexedDB/">IndexedDB databases</a> or <a href="#cache-objects"><code>Cache</code> objects</a>.
    <br><br>
    Service Workers are not considered "installed" until the <code>oninstall</code> event handler completes. Given that many tasks, such as populating caches, may take a long time and are asynchronous, <a href="#wait-until-method">mechanisms are provided</a> to let applications signal to the user agent when they consider themselves prepared to handle further events.
    <br><br>
    If no <code>oninstall</code> event handler is registered, the Service Worker is considered to be <dfn id="successfully-installed">successfully installed</dfn>.
    <br><br>
    If any <code>oninstall</code> handler throws an exception, or if any lifetime extension via <code>event.waitUntil()</code> fails (via Promise rejection), installation fails and activation is not carried out.
    <br><br>
    Assuming a worker <a href="#successfully-installed">is successfully installed</a>, it is now considered the <dfn id="worker-in-waiting">worker in waiting</dfn>. There may be only one <a href="#navigator-service-worker-current">active worker</a> and one <a href="#worker-in-waiting">worker in waiting</a> for a given <a href="#url-scope">url scope</a>.
    </li>
    <li><em><code>onactivate</code></em>:
    <br>
    After successful installation and just prior to receiving <a href="#functional-events">functional events</a> (e.g., <code><a href="#fetch-event">fetch</a></code>), the <code>activate</code> event is dispatched. The primary use of <code>onactivate</code> is for cleanup of resources used in previous versions of a Service Worker script.
    <br><br>
    <div class="note">Like <code>install</code> event, this event may extend its lifetime using <code>event.waitUntil()</code>, however developers should note that activation is particularly performance sensitive. Performance sensitive events may be queued and will be delayed until successful completion of <code>onactivate</code>.</div>
    </li>
  </ol>

  <p>User Agents may request updated Service Worker scripts "in the background" while <a href="#document-control">controlled</a> documents for an existing Service Worker and url scope are active. Successful fetch, startup, and <code>oninstall</code> <i>do not</i> guarantee that the <a href="#worker-in-waiting">worker-in-waiting</a> will begin to immediately handle <a href="#functional-events">functional events</a>. An existing Service Worker script will continue to service documents it controls (and will continue to control new documents in the <a href="#url-scope">url scope</a>) so long as any documents it <a href="#document-control">controlled</a> remain. API exists on the <a href="#service-worker-obj">Service Worker</a> to enable immediate activation but this is not the default behavior.<p>

  <p>Once a service worker becomes active, the user agent may dispatch <a href="#functional-events">functional events</a>. These events model various user-agent generated operations; for example the <code><a href="#fetch-event">fetch</a></code> event handling HTTP requests.</p>

<!--
<spec-section>
<h1 id="offline-example">Example: Offline Web Applications</h1>

<spec-idl class="prettyprint">
// TODO(slightlyoff)
</spec-idl>

<p></p>
</spec-section>
-->

</spec-clause>

<spec-clause id="document-context">
  <h1 id="h1-document-context">Document Context</h1>

  <p>Example: Bootstrapping with a ServiceWoker</p>

<spec-idl class="prettyprint">// scope defaults to "/*"
navigator.serviceWorker.register("/assets/v1/serviceworker.js").then(
  function(serviceWorker) {
    console.log("success!");
    serviceWorker.postMessage("Howdy from your installing page.");
  },
  function(why) {
    console.error("Installing the worker failed!:", why);
  });</spec-idl>

  <spec-section id="service-worker-obj">
    <h1 id="h1-service-worker-obj"><code>ServiceWorker</code></h1>

    <p></p>
<spec-idl>[Constructor()] // no-op constructor
interface <dfn id="service-worker-interface" title="ServiceWorker">ServiceWorker</dfn> : <a href="http://goo.gl/mkHcfY">Worker</a> {
  readonly attribute DOMString scope;
  readonly attribute DOMString url;
  readonly attribute <a href="#service-worker-state-enum">ServiceWorkerState</a> state;

  // event
  attribute <a href="http://goo.gl/3nnYrx">EventHandler</a> onstatechange;
};

enum <dfn id="service-worker-state-enum" title="State">ServiceWorkerState</dfn> {
  "installing",
  "installed",
  "activating",
  "activated",
  "redundant"
};</spec-idl>

    <p>The <code>ServiceWorker</code> interface represents the document-side view of a Service Worker. This object provides a no-op constructor. Callers should note that only <code>ServiceWorker</code> objects created by the user agent (see <code>navigator.serviceWorker.installing</code>, <code>navigator.serviceWorker.waiting</code> and <code>navigator.serviceWorker.current</code>) will provide meaningful functionality.</p>

    <spec-section id="service-worker-scope">
      <h1 id="h1-service-worker-scope"><code>scope</code></h1>

      <p>The <code>scope</code> attribute must return the <a href="http://url.spec.whatwg.org/#concept-url-serializer">serialization</a> of the url representing the <a href="#url-scope">url scope</a> of the <a href="#service-worker-interface">ServiceWorker</a> object.</p>

      <p>The <code>scope</code> of a <code>ServiceWorker</code> reflects the scope of the <code>ServiceWorker</code>'s <a href="#registration-internal-interface">registration</a>. For example, consider a document created by a navigation to <code>https://example.com/app.html</code> which <a href="#on-navigation-request-algorithm">matches</a> via the following registration call which has been previously executed:</p>

<spec-idl class="prettyprint">// Script on the page https://example.com/app.html
navigator.serviceWorker.register("/service_worker.js", { scope: "/*" });</spec-idl>

      <p>The value of <code>navigator.serviceWorker.current.scope</code> will be <code>"https://example.com/*"</code>.</p>
    </spec-section>

    <spec-section id="service-worker-url">
      <h1 id="h1-service-worker-url"><code>url</code></h1>

      <p>The <code>url</code> attribute must return the <a href="http://url.spec.whatwg.org/#concept-url-serializer">serialization</a> of the url identifying the script resource that is running in the worker that the <a href="#service-worker-interface">ServiceWorker</a> object represents.</p>

      <p>Similarly, in the above example, the value of <code>navigator.serviceWorker.current.url</code> will be <code>"https://example.com/service_worker.js"</code>. The <code>url</code> property is always an <a href="http://url.spec.whatwg.org/#concept-absolute-url">absolute URL</a> corresponding to the script file which the Service Worker evaluates.</p>
    </spec-section>

    <spec-section id="service-worker-on-state-change">
      <h1 id="h1-service-worker-on-state-change"><code>onstatechange</code></h1>

      <p><code>onstatechange</code> is the <a href="http://goo.gl/rBfiz0">event handler</a> that must be supported as attribute by the <code><a href="#service-worker-interface">ServiceWorker</a></code> object. A <code>statechange</code> event using the <code><a href="http://goo.gl/Mzv7Dv">Event</a></code> interface is dispatched on <code><a href="#service-worker-interface">ServiceWorker</a></code> object when the <code>state</code> attribute of the <code>ServiceWorker</code> object is changed.</p>
    </spec-section>
  </spec-section>

  <spec-section id="navigator-service-worker">
    <h1 id="h1-navigator-service-worker"><code>navigator.serviceWorker</code></h1>

    <p><code>navigator.serviceWorker</code> is an object which provides access to registration, removal, upgrade, and communication with service workers that are (or will become) active for the current document.</p>

    <p>The <code>current</code> property of this object provides a reference to the service worker which was consulted during the construction of the current document (if any).</p>

    <p>Communication with these workers is provided via standard <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/web-messaging.html">HTML5 messaging APIs</a>, and <a href="http://www.w3.org/TR/workers/#dom-worker-postmessage">messaging occurs as per usual with Web Workers</a>.</p>

<spec-idl>partial interface <a href="http://goo.gl/I7WAhg">Navigator</a> {
  readonly attribute <a href="#service-worker-container-interface">ServiceWorkerContainer</a> serviceWorker;
};

interface <dfn id="service-worker-container-interface" title="ServiceWorkerContainer">ServiceWorkerContainer</dfn> {
  [<a href="http://heycam.github.io/webidl/#Unforgeable">Unforgeable</a>] readonly attribute <a href="#service-worker-interface">ServiceWorker</a>? installing;
  [<a href="http://heycam.github.io/webidl/#Unforgeable">Unforgeable</a>] readonly attribute <a href="#service-worker-interface">ServiceWorker</a>? waiting;
  [<a href="http://heycam.github.io/webidl/#Unforgeable">Unforgeable</a>] readonly attribute <a href="#service-worker-interface">ServiceWorker</a>? current;

  <a href="http://goo.gl/3TobQS">Promise</a>&lt;<a href="#service-worker-interface">ServiceWorker</a>[]?&gt; getAll();
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;<a href="#service-worker-interface">ServiceWorker</a>&gt; register(DOMString <var>url</var>, optional <a href="#registration-option-list-dictionary">RegistrationOptionList</a> <var>options</var>);
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;any&gt; unregister(DOMString? <var>scope</var>);
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;<a href="#service-worker-interface">ServiceWorker</a>&gt; whenReady();

  // events
  attribute <a href="http://goo.gl/3nnYrx">EventHandler</a> onupdatefound;
  attribute <a href="http://goo.gl/3nnYrx">EventHandler</a> oncurrentchange;
  attribute <a href="http://goo.gl/3nnYrx">EventHandler</a> onreloadpage;
  attribute <a href="http://goo.gl/3nnYrx">EventHandler</a> onerror;
};

dictionary <dfn id="registration-option-list-dictionary" title="RegistrationOptionList">RegistrationOptionList</dfn> {
  DOMString scope = "*";
};

interface <dfn id="reload-page-event-interface" title="ReloadPageEvent">ReloadPageEvent</dfn> : <a href="http://goo.gl/UVs0Yt">Event</a> {
  void waitUntil(<a href="http://goo.gl/3TobQS">Promise</a>&lt;any&gt; <var>f</var>);
};</spec-idl>

  <spec-section id="navigator-service-worker-current">
    <h1 id="h1-navigator-service-worker-current"><code>current</code></h1>

    <p><code>navigator.serviceWorker.current</code> must return a reference to the current <a href="#service-worker"><code>ServiceWorker</code></a> for the document. <code>navigator.serviceWorker.current</code> returns <code>null</code> if the current document was not <a href="#scope-match-algorithm">created under a service worker</a>, or if the state is not <code>activating</code> or <code>activated</code>.<!-- FIXME(jungkees) state property should be defined. --></p>
  </spec-section>
  <spec-section id="navigator-service-worker-getAll">
    <h1 id="h1-navigator-service-worker-getAll"><code>getAll()</code></h1>

    <p><code>navigator.serviceWorker.getAll()</code> method must return a promise that resolves with the array of the ServiceWorker objects in <code>installing</code>, <code>installed</code>, <code>activating</code> and <code>activated</code> states.<!-- FIXME(jungkees) state property should be defined. --></p>
  </spec-section>
  <spec-section id="navigator-service-worker-register">
    <h1 id="h1-navigator-service-worker-register"><code>register()</code></h1>

    <p><code>navigator.serviceWorker.register(url, options)</code> method must run the <a href="#registration-algorithm">Registration algorithm</a> passing <var>url</var> and <var>options</var>.<var>scope</var> as the arguments.</p>
  </spec-section>
  <spec-section id="navigator-service-worker-unregister">
    <h1 id="h1-navigator-service-worker-unregister"><code>unregister()</code></h1>

    <p><code>navigator.serviceWorker.unregister(scope)</code> method must run the <a href="#unregistration-algorithm">Unregistration algorithm</a> passing <var>scope</var> as the argument.</p>
  </spec-section>
  <spec-section id="navigator-service-worker-when-ready">
    <h1 id="h1-navigator-service-worker-when-ready"><code>whenReady()</code></h1>

    <p><code>navigator.serviceWorker.whenReady()</code> method must return a promise that resolves with the associated <a href="#service-worker"><code>ServiceWorker</code></a> object when it becomes either waiting or current worker for the document. That is, the <code>state</code> of the <a href="#service-worker"><code>ServiceWorker</code></a> is either <code>installed</code>, <code>activating</code> or <code>activated</code>, and the promise never rejects in any case.</p>
  </spec-section>
  <spec-section id="navigator-service-worker-onupdatefound">
    <h1 id="h1-navigator-service-worker-onupdatefound"><code>onupdatefound</code></h1>

    <p><code>navigator.serviceWorker.onupdatefound</code> is the <a href="http://goo.gl/rBfiz0">event handler</a> that must be supported as attribute by the <code><a href="#service-worker-container-interface" title="ServiceWorkerContainer">ServiceWorkerContainer</a></code> object. An <code>updatefound</code> event using the <code><a href="http://goo.gl/Mzv7Dv">Event</a></code> interface is dispatched on <code><a href="#service-worker-container-interface" title="ServiceWorkerContainer">ServiceWorkerContainer</a></code> object when the state of the associated <code><a href="#service-worker-interface" title="ServiceWorker">ServiceWorker</a></code> changes its value to <code>installing</code> such that <code>navigator.serviceWorker.installing</code> becomes a new worker. (See step 4 of <a href="#installation-algorithm">_Installation algorithm</a>)</p>
  </spec-section>
  <spec-section id="navigator-service-worker-oncurrentchange">
    <h1 id="h1-navigator-service-worker-oncurrentchange"><code>oncurrentchange</code></h1>

    <p><code>navigator.serviceWorker.oncurrentchange</code> is the <a href="http://goo.gl/rBfiz0">event handler</a> that must be supported as attribute by the <code><a href="#service-worker-container-interface" title="ServiceWorkerContainer">ServiceWorkerContainer</a></code> object. An <code>currentchange</code> event using the <code><a href="http://goo.gl/Mzv7Dv">Event</a></code> interface is dispatched on <code><a href="#service-worker-container-interface" title="ServiceWorkerContainer">ServiceWorkerContainer</a></code> object when the state of the associated <code><a href="#service-worker-interface" title="ServiceWorker">ServiceWorker</a></code> changes its value to <code>activated</code> such that <code>navigator.serviceWorker.current</code> changes to this associated <code><a href="#service-worker-interface" title="ServiceWorker">ServiceWorker</a></code> object. (See step 8 of <a href="#activation-algorithm">_Activation algorithm</a>)</p>
  </spec-section>
  <spec-section id="navigator-service-worker-onreloadpage">
    <h1 id="h1-navigator-service-worker-onreloadpage"><code>onreloadpage</code></h1>

    <p><code>navigator.serviceWorker.onreloadpage</code> is the <a href="http://goo.gl/rBfiz0">event handler</a> that must be supported as attribute by the <code><a href="#service-worker-container-interface" title="ServiceWorkerContainer">ServiceWorkerContainer</a></code> object. An event named <code>reloadpage</code> using the <code><a href="#reload-page-event-interface">ReloadPageEvent</a></code> interface is dispatched on <code><a href="#service-worker-container-interface" title="ServiceWorkerContainer">ServiceWorkerContainer</a></code> object when <code><a href="#reloadall-method">navigator.serviceWorker.clients.reloadAll()</a></code> method is called.</p>
  </spec-section>
  <spec-section id="navigator-service-worker-onerror">
    <h1 id="h1-navigator-service-worker-onerror"><code>onerror</code></h1>

    <p><code>navigator.serviceWorker.onerror</code> is the <a href="http://goo.gl/rBfiz0">event handler</a> that must be supported as attribute by the <code><a href="#service-worker-container-interface" title="ServiceWorkerContainer">ServiceWorkerContainer</a></code> object. An event named <code>error</code> using the <code><a href="http://goo.gl/FKuWgu">ErrorEvent</a></code> interface is dispatched on <code><a href="#service-worker-container-interface" title="ServiceWorkerContainer">ServiceWorkerContainer</a></code> object for any error from the associated <code><a href="#service-worker-interface" title="ServiceWorker">ServiceWorker</a></code> objects.</p>
  </spec-section>
</spec-section>
</spec-clause>

<spec-clause id="execution-context">
  <h1 id="h1-execution-context">Execution Context</h1>

  <P>Example: Serving Cached Resources</P>

<spec-idl class="prettyprint">// caching.js
this.addEventListener("install", function(e) {
  // Create a cache of resources. Begins the process of fetching them.
  var shellResources = new Cache(
    "/app.html",
    "/assets/v1/base.css",
    "/assets/v1/app.js",
    "/assets/v1/logo.png",
    "/assets/v1/intro_video.webm",
  );

  // The coast is only clear when all the resources are ready.
  e.waitUntil(shellResources.ready());

  // Add Cache to the global so it can be used later during onfetch
  caches.set("shell-v1", shellResources);
});

this.addEventListener("fetch", function(e) {
  // No "onfetch" events are dispatched to the ServiceWorker until it
  // successfully installs.

  // All operations on caches are async, including matching URLs, so we use
  // Promises heavily. e.respondWith() even takes Promises to enable this:
  e.respondWith(
    caches.match(e.request).catch(function() {
      return e.default();
    }).catch(function() {
      return caches.match("/fallback.html");
    })
  );
});</spec-idl>

  <spec-section id="service-worker-global-scope">
    <h1 id="h1-service-worker-global-scope"><code>ServiceWorkerGlobalScope</code></h1>

<spec-idl>[<a href="http://heycam.github.io/webidl/#Global">Global</a>]
interface <dfn id="service-worker-global-scope-interface" title="ServiceWorkerGlobalScope">ServiceWorkerGlobalScope</dfn> : <a href="http://goo.gl/xBhqNU">WorkerGlobalScope</a> {
  readonly attribute <a href="#cache-list-interface">CacheList</a> caches;
  // A container for a list of window objects, identifiable by ID, that
  // correspond to windows (or workers) that are "controlled" by this SW
  readonly attribute <a href="#service-worker-clients-interface">ServiceWorkerClients</a> clients;
  [<a href="http://heycam.github.io/webidl/#Unforgeable">Unforgeable</a>] readonly attribute DOMString scope;

  <a href="#response-promise-interface">ResponsePromise</a>&lt;any&gt; fetch((<a href="#request-interface">Request</a> or [<a href="http://goo.gl/VdmjMo">EnsureUTF16</a>] DOMString) <var>request</var>);

  void update();
  void unregister();

  attribute <a href="http://goo.gl/3nnYrx">EventHandler</a> oninstall;
  attribute <a href="http://goo.gl/3nnYrx">EventHandler</a> onactivate;
  attribute <a href="http://goo.gl/3nnYrx">EventHandler</a> onfetch;
  attribute <a href="http://goo.gl/3nnYrx">EventHandler</a> onbeforeevicted;
  attribute <a href="http://goo.gl/3nnYrx">EventHandler</a> onevicted;

  // The event.source of these MessageEvents are instances of Client
  attribute <a href="http://goo.gl/3nnYrx">EventHandler</a> onmessage;

  // close() method inherited from WorkerGlobalScope is not exposed.
};
</spec-idl>

    <p>The <code>ServiceWorkerGlobalScope</code> interface represents the global execution context of a Service Worker. <code>ServiceWorkerGlobalScope</code> object provides generic, event-driven, time-limited script execution contexts that run at an origin. Once successfully <a href="#navigator-service-worker-register">registered</a>, a Service Worker is started, kept alive and killed by their relationship to events, not documents. Any type of synchronous requests MUST NOT be initiated inside of a Service Worker.</p>

    <spec-section id="service-worker-global-scope-caches">
      <h1 id="h1-service-worker-global-scope-caches"><code>caches</code></h1>

      <p><code>self.caches</code> must return the <code><a href="#cache-list-interface">CacheList</a></code> object that is the global asychronous map object for the <code><a href="#service-worker-global-scope-interface">ServiceWorkerGlobalScope</a></code> execution context containing the cache objects keyed by the name of the caches. Caches are always enumerable via <code>self.caches</code> in insertion order (per <a href="http://goo.gl/gNnDPO">ECMAScript 6 Map objects</a>.)</p>
    </spec-section>
    <spec-section id="service-worker-global-scope-clients">
      <h1 id="h1-service-worker-global-scope-clients"><code>clients</code></h1>

      <p><code>self.clients</code> must return the <code><a href="#service-worker-clients-interface">ServiceWorkerClients</a></code> object containing a list of client objects, identifiable by ID, that correspond to windows or workers that are <a href="#document-control">controlled</a> by this Service Worker.</p>
    </spec-section>
    <spec-section id="service-worker-global-scope-scope">
      <h1 id="h1-service-worker-global-scope-scope"><code>scope</code></h1>

      <p><code>self.scope</code> must return the pattern string for which this Service Worker instance was registered.</p>
    </spec-section>
    <spec-section id="service-worker-global-scope-fetch">
      <h1 id="h1-service-worker-global-scope-fetch"><code>fetch(request)</code></h1>

      <p><code>self.fetch(request)</code> method must run the <a href="http://goo.gl/fGMifs">fetch algorithm</a> passing <var>request</var> as the argument.</p>
    </spec-section>
    <spec-section id="service-worker-global-scope-update">
      <h1 id="h1-service-worker-global-scope-update"><code>update()</code></h1>

      <p><code>update()</code> pings the server for an updated version of this script without consulting caches. <code>self.update()</code> method must run the <a href="#soft-update-algorithm">_SoftUpdate algorithm</a> passing its serviceWorkerRegistration object as the argument which is the result of running the <a href="#get-registration-algorithm">_GetRegistration algorithm</a> with <code>self.scope</code> as the argument. (This is conceptually the same operation that UA does maximum once per every 24 hours.)</p>
    </spec-section>
    <spec-section id="service-worker-global-scope-unregister">
      <h1 id="h1-service-worker-global-scope-unregister"><code>unregister()</code></h1>

      <p><code>self.unregister()</code> method must run the <a href="#unregistration-algorithm">Unregistration algorithm</a> implicitly passing <code>self.scope</code> as the argument.</p>
    </spec-section>
    <spec-section id="service-worker-global-scope-onmessage">
      <h1 id="h1-service-worker-global-scope-onmessage"><code>onmessage</code></h1>

      <p><code>self.onmessage</code> is the <a href="http://goo.gl/rBfiz0">event handler</a> that must be supported as attribute by the <code>ServiceWorkerGlobalScope</code> object. <code>ServiceWorkerGlobalScope</code> objects act as if they had an implicit <code><a href="http://goo.gl/tHBrI6">MessagePort</a></code> associated with them. This port is part of a channel that is set up when the worker is created, but it is not exposed. This object must never be garbage collected before the <code>ServiceWorkerGlobalScope</code> object.</p>
      <p>All messages received by that port must immediately be retargeted at the <code>ServiceWorkerGlobalScope</code> object. That is, an event named <code>message</code> using the <code><a href="http://goo.gl/S5e0b6">MessageEvent</a></code> interface is dispatched on ServiceWorkerGlobalScope object. The <code>event.source</code> of these <code><a href="http://goo.gl/S5e0b6">MessageEvent</a></code>s are instances of <code><a href="#client-interface">Client</a></code>.</p>
    </spec-section>

  </spec-section>
  <spec-section id="client">
    <h1 id="h1-client"><code>Client</code></h1>

<spec-idl>[Constructor()] // no-op constructor
interface <dfn id="client-interface" title="Client">Client</dfn> {
  readonly attribute unsigned long id;
  void postMessage(any <var>message</var>, DOMString <var>targetOrigin</var>,
                   optional sequence&lt;<a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/common-dom-interfaces.html#transferable">Transferable</a>&gt; <var>transfer</var>);
};
</spec-idl>

    <p>The <code>Client</code> interface represents the window or the worker (defined as client) that is <a href="#document-control">controlled</a> by the Service Worker. This object provides a no-op constructor. Callers should note that only <code>Client</code> objects created by the user agent (see <a href="#get-serviced-method"><code>this.clients.getServiced()</code></a>) will provide meaningful functionality.</p>

    <p>The <code>id</code> of a <code>Client</code> identifies the specific client object from the list of client objects serviced by the Service Worker. The <code>postMessage(message, targetOrigin, transfer)</code> method of a <code><a href="#client-interface">Client</a></code>, when called, causes a <code><a href="http://goo.gl/4SLWiH">MessageEvent</a></code> to be dispatched at the client object.</p>

  </spec-section>
  <spec-section id="service-worker-clients">
    <h1 id="h1-service-worker-clients"><code>ServiceWorkerClients</code></h1>

<spec-idl>interface <dfn id="service-worker-clients-interface" title="ServiceWorkerClients">ServiceWorkerClients</dfn> {
  // A list of client objects, identifiable by ID, that correspond to windows
  // (or workers) that are "controlled" by this SW
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;<a href="#client-interface">Client</a>[]?&gt; getServiced();
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;any&gt; reloadAll();
};
</spec-idl>

    <p>The <code>ServiceWorkerClients</code> interface represents a container for a list of <code><a href="#client-interface">Client</a></code> objects.</p>
    <spec-section id="get-serviced-method">
      <h1 id="h1-get-serviced-method"><code>getServiced()</code></h1>
      <p>The <code>getServiced()</code> method of a <code>ServiceWorkerClients</code>, when called, returns a <a href="http://goo.gl/3TobQS">Promise</a> that will resolve with a list of <code><a href="#client-interface">Client</a></code> objects that are <a href="#document-control">controlled</a> by this Service Worker.</p>
    </spec-section>
    <spec-section id="reloadall-method">
      <h1 id="h1-reloadall-method"><code>reloadAll()</code></h1>

      <p><code>reloadAll()</code> provides a mechanism for the worker to request synchronized re-fetch of all documents whose URLs match the registration's <a href="#url-scope">url scope</a>. An event named <code>reloadpage</code> is dispatched on the <code>navigator.serviceWorker</code> object of each document. The in-document handlers may allow the event to continue, request an extension (via <a href="#wait-until-method"><code>e.waitUntil()</code></a>), or cancel the collective reload by calling <a href="http://goo.gl/2zH6ie"><code>e.preventDefault()</code></a>.</p>

      <!-- If the group-reload is canceled, // FIXME(slightlyoff) -->
    </spec-section>
  </spec-section>

  <spec-section id="request-objects">
    <h1 id="h1-request-objects"><code>Request</code> Objects</h1>

<spec-idl>
interface <dfn id="request-promise-interface" title="RequestPromise">RequestPromise</dfn> : <a href="http://goo.gl/3TobQS">Promise</a> {
};

[Constructor(optional <a href="#request-init-dictionary">RequestInit</a> <var>init</var>)]
interface <dfn id="request-interface" title="Request">Request</dfn> {
  attribute unsigned long timeout;
  attribute DOMString url;
  attribute <a href="http://goo.gl/M46tpy">ByteString</a> method;
  readonly attribute DOMString origin;
  readonly attribute <a href="#mode-enum">Mode</a> mode;
  attribute boolean synchronous;
  readonly attribute unsigned long redirectCount;
  attribute boolean forcePreflight;
  attribute boolean forceSameOrigin;
  attribute boolean omitCredentials;
  readonly attribute DOMString referrer;
  readonly attribute <a href="#header-map-interface">HeaderMap</a> headers; // alternative: sequence&lt;Header&gt; headers;
  attribute any body;
};

dictionary <dfn id="request-init-dictionary" title="RequestInit">RequestInit</dfn> {
  unsigned long timeout = 0;
  DOMString url;
  boolean synchronous = false;
  boolean forcePreflight = false;
  boolean forceSameOrigin = false;
  boolean omitCredentials = false;
  <a href="http://goo.gl/M46tpy">ByteString</a> method = "GET";
  <a href="#header-map-interface">HeaderMap</a> headers;
  any body;
};

enum <dfn id="mode-enum" title="Mode">Mode</dfn> {
  "same origin",
  "tainted x-origin",
  "CORS"
};

[<a href="http://goo.gl/lJQaAt">MapClass</a>(DOMString, DOMString)]
interface <dfn id="header-map-interface" title="HeaderMap">HeaderMap</dfn> {
};
</spec-idl>
  </spec-section>

  <spec-section id="response-objects">
    <h1 id="h1-response-objects"><code>Response</code> Objects</h1>

    <p><code>Resposne</code> objects model HTTP responses.</p>

<spec-idl>
interface <dfn id="response-promise-interface" title="ResponsePromise">ResponsePromise</dfn> : <a href="http://goo.gl/3TobQS">Promise</a> {
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;<a href="http://goo.gl/dqRadv">Blob</a>&gt; toBlob();
};

[Constructor]
interface <dfn id="abstract-response-interface" title="AbstractResponse">AbstractResponse</dfn> {
};

interface <dfn id="opaque-response-interface" title="OpaqueResponse">OpaqueResponse</dfn> : <a href="#abstract-response-interface">AbstractResponse</a> {
  readonly attribute unsigned short status;
  readonly attribute <a href="http://goo.gl/M46tpy">ByteString</a> statusText;
  readonly attribute <a href="http://goo.gl/M46tpy">ByteString</a> method;
  // Returns a filtered list of headers. See <a href="#opaque-response">prose for details</a>.
  getter <a href="#header-map-interface">HeaderMap</a> headers();
  // No setter for headers
  readonly attribute DOMString url;
};

interface <dfn id="cors-response-interface" title="CORSResponse">CORSResponse</dfn> : <a href="#response-interface">Response</a> {
  getter <a href="#header-map-interface">HeaderMap</a> headers();
};

[Constructor(optional <a href="#response-init-dictionary">ResponseInit</a> <var>responseInitDict</var>)]
interface <dfn id="response-interface" title="Response">Response</dfn> : <a href="#abstract-response-interface">AbstractResponse</a> {
  attribute unsigned short status;
  attribute <a href="http://goo.gl/M46tpy">ByteString</a> statusText;
  attribute <a href="http://goo.gl/M46tpy">ByteString</a> method;
  getter <a href="#header-map-interface">HeaderMap</a> headers();
  setter void headers(<a href="#header-map-interface">HeaderMap</a> items);
  attribute DOMString url;
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;<a href="http://goo.gl/dqRadv">Blob</a>&gt; toBlob();
};

dictionary <dfn id="response-init-dictionary" title="ResponseInit">ResponseInit</dfn> {
  unsigned short status = 200;
  <a href="http://goo.gl/M46tpy">ByteString</a> statusText = "OK";
  <a href="http://goo.gl/M46tpy">ByteString</a> method;
  <a href="#header-map-interface">HeaderMap</a> headers;
};
</spec-idl>

    <spec-section id="abstract-response">
      <h1 id="h1-abstract-response"><code>AbstractResponse</code></h1>

      <p><code>AbstractResponse</code> is a superclass for all <code>Resposne</code> types. It should not be directly constructed (although, for compatibility with JavaScript, a constructor is provided).</p>
    </spec-section>

    <spec-section id="response">
      <h1 id="h1-response"><code>Response</code></h1>

      <p><code>Response</code> objects are mutable and constructable. They model HTTP responses. The <code>fetch()</code> API returns this type for same-origin responses.</p>

      <p class="note">It may be possible to set the <code>Location</code> header of a <code>Response</code> object to someplace not in the current origin but this is not a security issue. Cross-origin response bodies are opaque to script, and since only same-origin documents will encounter these responses, the only systems the Service Worker can "lie to" are same-origin (and therefore safe from the perspective of other origins).</p>
    </spec-section>

    <spec-section id="header">
      <h1 id="h1-header"><code>headers</code></h1>
      <!-- TODO(slightlyoff): whitelist readable headers -->
    </spec-section>

    <spec-section id="opaque-response">
      <h1 id="h1-opaque-response"><code>OpaqueResponse</code></h1>

      <p><code>OpaqueResponse</code> objects are immutable but constructable. The <code>fetch()</code> API returns this type for cross-origin responses.</p>

      <p>Their role is to encapsulate the security properties of the web platform. As such, their <code>body</code> attribute will always be <code>undefined</code> and the list of readable <code>headers</code> is heavily filtered.</p>

      <p><code>OpaqueResponse</code> objects may be forwarded on to rendering documents in exactly the same way as mutable <code>Response</code> objects.</p>
    </spec-section>

    <!-- TODO(slightlyoff): whitelist readable headers -->

    <spec-section id="cors-response">
      <h1 id="h1-cors-response"><code>CORSResponse</code></h1>
    </spec-section>
  </spec-section>

  <!--spec-section id="fetch">
    <h1><code>fetch()</code></h1>
  </spec-section--><!--#FIXME(jungkees) if wrong: fetch(request) is defined in ServiceWorkerGlobalScope section-->
  <spec-section id="cache-objects">
    <h1 id="h1-cache-objects">Caches</h1>

    <p>To allow authors to fully manage their content caches for offline use, the <code><a href="#service-worker-global-scope-interface">ServiceWorkerGlobalScope</a></code> execution context provides the caching methods largely conforming to <a href="http://goo.gl/gNnDPO">ECMAScript 6 Map objects</a> with additional convenience methods. A domain can have multiple, named <code><a href="#cache-interface">Cache</a></code> objects, whose contents are entirely under the control of scripts. Caches are not shared across domains, and they are completely isolated from the browser's HTTP cache.</p>

    <spec-section id="cache-lifetimes">
      <h1 id="h1-cache-lifetimes">Understanding Cache Lifetimes</h1>

      <p>The <code><a href="#cache-interface">Cache</a></code> instances are not part of the browser's HTTP cache. The <code><a href="#cache-interface">Cache</a></code> objects are exactly what authors have to manage themselves. The <code><a href="#cache-interface">Cache</a></code> objects do not get updated unless authors explicitly request them to be. The <code><a href="#cache-interface">Cache</a></code> objects do not expire unless authors delete the entries. The <code><a href="#cache-interface">Cache</a></code> objects do not disappear just because the Service Worker script is updated. That is, caches are not updated automatically. Updates must be manually managed. This implies that authors should version their caches by name and make sure to use the caches only from the version of the ServiceWorker that can safely operate on.</p>
    </spec-section>

    <spec-section id="cache">
      <h1 id="h1-cache"><code>Cache</code></h1>
<spec-idl>
[Constructor((<a href="#request-interface">Request</a> or <a href="#response-interface">Response</a> or [<a href="http://goo.gl/VdmjMo">EnsureUTF16</a>] DOMString)... <var>items</var>)]
interface <dfn id="cache-interface" title="Cache">Cache</dfn> {
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;<a href="#response-interface">Response</a>&gt; match((<a href="#request-interface">Request</a> or [<a href="http://goo.gl/VdmjMo">EnsureUTF16</a>] DOMString) <var>request</var>);
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;<a href="#response-interface">Response</a>[]&gt; matchAll((<a href="#request-interface">Request</a> or [<a href="http://goo.gl/VdmjMo">EnsureUTF16</a>] DOMString) <var>request</var>);
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;<a href="#request-interface">Request</a>[]&gt; keys((<a href="#request-interface">Request</a> or [<a href="http://goo.gl/VdmjMo">EnsureUTF16</a>] DOMString) <var>filterRequest</var>);
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;<a href="#response-interface">Response</a>[]&gt; add((<a href="#request-interface">Request</a> or <a href="#response-interface">Response</a> or [<a href="http://goo.gl/VdmjMo">EnsureUTF16</a>] DOMString)... <var>items</var>);
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;<a href="#response-interface">Response</a>&gt; set((<a href="#request-interface">Request</a> or [<a href="http://goo.gl/VdmjMo">EnsureUTF16</a>] DOMString) <var>request</var>, <a href="#response-interface">Response</a> <var>response</var>);
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;any[]&gt; delete((<a href="#request-interface">Request</a> or [<a href="http://goo.gl/VdmjMo">EnsureUTF16</a>] DOMString) <var>request</var>);
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;<a href="#response-interface">Response</a>[]&gt; ready();
};
</spec-idl>
    </spec-section>
    <spec-section id="cache-list">
      <h1 id="h1-cache-list"><code>CacheList</code></h1>

<spec-idl>
[<a href="http://goo.gl/lJQaAt">MapClass</a>(DOMString, <a href="#cache-interface">Cache</a>)]
interface <dfn id="cache-list-interface" title="CacheList">CacheList</dfn> {
  <a href="#response-promise-interface">ResponsePromise</a>&lt;any&gt; match([<a href="http://goo.gl/VdmjMo">EnsureUTF16</a>] DOMString <var>url</var>, optional DOMString <var>cacheName</var>);
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;<a href="#cache-interface">Cache</a>&gt; get(DOMString <var>key</var>);
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;boolean&gt; has(DOMString <var>key</var>);
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;any&gt; set(DOMString <var>key</var>, <a href="#cache-interface">Cache</a> <var>val</var>);
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;any&gt; clear();
  <a href="#cache-list-interface">CacheList</a> items();
  DOMString[] keys();
  <a href="#cache-interface">Cache</a>[] values();
  getter unsigned long size();
};
</spec-idl>

      <p><span class="fixme"><strong>Issue</strong>: the following issues should be addressed in the WebIDL specification: the methods <code>keys()</code> and <code>values()</code> are not allowed to be declared as interface members of an interface declared with the [<a class="external" href="http://goo.gl/lJQaAt">MapClass</a>] extended attribute; the return type of <code>get(key)</code>, <code>has(key)</code>, <code>set(key, val)</code>, <code>clear()</code>, <code>delete(key)</code> is meant to be declared as pre-defined IDL fragment. Namely, the interface declared with [<a class="external" href="http://goo.gl/lJQaAt">MapClass</a>] extended attribute cannot fully support creating asynchronous map objects.</span></p>

    </spec-section>
  </spec-section>
  <spec-section id="events">
    <h1 id="h1-events">Events</h1>

    <spec-section id="install-phase-event">
      <h1 id="h1-install-phase-event"><code>InstallPhaseEvent</code></h1>

<spec-idl>
interface <dfn id="install-phase-event-interface" title="InstallPhaseEvent">InstallPhaseEvent</dfn> : <a href="http://goo.gl/UVs0Yt">Event</a> {
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;any&gt; waitUntil(<a href="http://goo.gl/3TobQS">Promise</a>&lt;any&gt; <var>f</var>);
};
</spec-idl>

      <p>Service Workers have two <a href="#lifecycle-events">Lifecycle events</a>, <code><a href="#install-event">install</a></code> and <code><a href="#activate-event">activate</a></code>. Service Workers use the <code><a href="#install-phase-event-interface">InstallPhaseEvent</a></code> interface for <code><a href="#activate-event">activate</a></code> event and the <code><a href="#install-event-interface">InstallEvent</a></code> interface, which inherits from the <code><a href="#install-phase-event-interface">InstallPhaseEvent</a></code> interface, for <code><a href="#install-event">install</a></code> event.</p>

      <spec-section id="wait-until-method">
        <h1 id="h1-wait-until-method"><code>event.waitUntil(f)</code></h1>

        <p><code>event.waitUntil(f)</code> method, when called in <code>oninstall</code> or <code>onactivate</code>, extends the lifetime of the event. When called in <code>oninstall</code>, it delays treating the installing worker until the passed <a href="http://goo.gl/3TobQS">Promise</a> resolves successfully. This is primarily used to ensure that a <code>ServiceWorker</code> is not active until all of the core caches it depends on are populated. When called in <code>onactivate</code>, it delays treating the activating worker until the passed <a href="http://goo.gl/3TobQS">Promise</a> resolves successfully. This is primarily used to ensure that any <a href="#functional-events">Functional events</a> are not dispatched to the <code>ServiceWorker</code> until it upgrades database schemas and deletes the outdated cache entries.</p>
      </spec-section>
    </spec-section>

    <spec-section id="install-event">
      <h1 id="h1-install-event"><code>install</code> Event</h1>

        <p>An event named <code><a href="#install-event">install</a></code> using the <code><a href="#install-event-interface">InstallEvent</a></code> interface is dispatched on <code>ServiceWorkerGlobalScope</code> object when the state of the associated <code>ServiceWorker</code> changes its value to <code>installing</code>. (See step 3 of <a href="#installation-algorithm">_Installation algorithm</a>)</p>
      <spec-section id="install-event-section">
        <h1 id="h1-install-event-section"><code>InstallEvent</code></h1>

<spec-idl>
interface <dfn id="install-event-interface" title="InstallEvent">InstallEvent</dfn> : <a href="#install-phase-event-interface">InstallPhaseEvent</a> {
  readonly attribute <a href="#service-worker-interface">ServiceWorker</a> activeWorker;
  void replace();
};
</spec-idl>

        <p>Service Workers use the <code><a href="#install-event-interface">InstallEvent</a></code> interface for <code><a href="#install-event">install</a></code> event.</p>
      </spec-section>
      <spec-section id="replace-method">
        <h1 id="h1-replace-method"><code>event.replace()</code></h1>

        <p><code>replace()</code> interacts with <code>waitUntil</code> method in the following way:</p>
        <ul>
          <li>Successful installation can be delayed by <code>waitUntil</code>, perhaps by subsequent event handlers.</li>
          <li>Replacement only happens upon successful installation</li>
          <li>Therefore, replacement of the <a href="#navigator-service-worker-current">active worker</a> (if any) is not immediate, however it may occur as soon as the end of the current turn.</li>
        </ul>
      </spec-section>
    </spec-section>
    <spec-section id="activate-event">
      <h1 id="h1-activate-event"><code>activate</code> Event</h1>

      <p>An event named <code><a href="#activate-event">activate</a></code> using the <code><a href="#install-phase-event">InstallPhaseEvent</a></code> interface is dispatched on <code>ServiceWorkerGlobalScope</code> object when the state of the associated <code>ServiceWorker</code> changes its value to <code>activating</code>. (See step 7 of <a href="#activation-algorithm">_Activation algorithm</a>)</p>
      <p>Service Workers use the <code><a href="#install-phase-event-interface">InstallPhaseEvent</a></code> interface for <code><a href="#activate-event">activate</a></code> event.</p>

      <!--spec-section id="activate-event">
        <h1><code>ActivateEvent</code></h1>
      </spec-section--><!-- FIXME(jungkees) if wrong: activate event uses InstallPhaseEvent rather than ActivateEvate -->
    </spec-section>
    <spec-section id="fetch-event">
      <h1 id="h1-fetch-event"><code>fetch</code> Event</h1>

      <spec-section id="fetch-event-section">
        <h1 id="h1-fetch-event-section"><code>FetchEvent</code></h1>

<spec-idl>
[Constructor]
interface <dfn id="fetch-event-interface" title="FetchEvent">FetchEvent</dfn> : <a href="http://goo.gl/UVs0Yt">Event</a> {
  readonly attribute <a href="#request-interface">Request</a> request;
  readonly attribute Client client; // The window issuing the request.
  readonly attribute <a href="#purpose-enum">Purpose</a> purpose;
  readonly attribute boolean isReload;

  void respondWith(<a href="http://goo.gl/3TobQS">Promise</a>&lt;<a href="#abstract-response-interface">AbstractResponse</a>&gt; <var>r</var>);
  <a href="http://goo.gl/3TobQS">Promise</a>&lt;any&gt; forwardTo([<a href="http://goo.gl/VdmjMo">EnsureUTF16</a>] DOMString <var>url</var>);
  <a href="#response-promise-interface">ResponsePromise</a>&lt;any&gt; default();
};

enum <dfn id="purpose-enum" title="Purpose">Purpose</dfn> {
  "connect",
  "font",
  "img",
  "object",
  "script",
  "style",
  "worker",
  "popup",
  "child",
  "navigate"
};
</spec-idl>
        <p>Service Workers use the <code><a href="#fetch-event-interface">FetchEvent</a></code> interface for <code><a href="#fetch-event">fetch</a></code> event.</p>
      </spec-section>
      <spec-section id="respond-with-method">
        <h1 id="h1-respond-with-method"><code>event.respondWith(r)</code></h1>

        <p>The <var>r</var> argument must resolve with a <a href="#response-interface">Response</a>, else a <a href="http://w3c.github.io/dom/#networkerror">NetworkError</a> is thrown. If the request is a top-level navigation and the return value is a <a href="#opaque-response-interface">OpaqueResponse</a> (an opaque response body), a <a href="http://w3c.github.io/dom/#networkerror">NetworkError</a> is thrown. The final URL of all successful (non network-error) responses is the <a href="#request-objects">request</a>ed URL. Renderer-side security checks about tainting for x-origin content are tied to the transparency (or opacity) of the <a href="#response-interface">Response</a> body, not URLs.</p>
      </spec-section>
      <spec-section id="is-reload-attribute">
        <h1 id="h1-is-reload-attribute"><code>event.isReload</code></h1>

        <p>Returns true if <var>event</var> was dispatched with the user's intention for the page reload, and false otherwise. Pressing the refresh button should be considered a reload while clicking a link and pressing the back button should not. The behavior of the <var>Ctrl+l enter</var> is left to the implementations of the user agents.</p>
      </spec-section>
    </spec-section>
  </spec-section>
</spec-clause>

<spec-clause id="security-considerations">
  <h1 id="h1-security-considerations">Security Considerations</h1>

  <p class="note">Service Workers should be implemented to be HTTPS-only. The reasons for SSL-only support include:</p>
  <ul>
    <li>Better to protect end users from man-in-the-middle attacks</li>
    <li>Do good by encouraging HTTPS adoption</li>
    <li>Existing "palyground" services (e.g. github.io) now work with HTTPS</li>
    <li>HTTPS is coming across much more of the web quickly</li>
    <li>Devtools can loosen the restriction for development (file://, localhost, etc.)</li>
  </ul>

  <spec-section id="origin-relativity">
    <h1 id="h1-origin-relativity">Origin Relativity</h1>

    <p class="note">One of the advanced concerns that major applications would encounter is whether they can be hosted from a CDN. By definition, these are servers in other places, often on other domains. Therefore, Service Workers cannot be hosted on CDNs. But they can include resources via <a href="http://goo.gl/Owcfs2">importScripts()</a>. The reason for this restriction is that Service Workers create the opportunity for a bad actor to turn a bad day into a bad eternity.</p>
  </spec-section>

  <spec-section id="x-origin-resources">
    <h1 id="h1-x-origin-resources">Cross-Origin Resources &amp; CORS</h1>

    <p class="note">Applications tend to cache items that come from a CDN or other domain. It is possible to request many of them directly using &lt;script&gt;, &lt;img&gt;, &lt;video&gt; and &lt;link&gt; elements. It would be hugely limiting if this sort of runtime collaboration broke when offline. Similarly, it is possible to XHR many sorts of off-domain resources when appropriate CORS headers are set.</p>
    <p>ServiceWorkers enable this by allowing <code>Cache</code>s to fetch and cache off-origin items. Some restrictions apply, however. First, unlike same-origin resources which are managed in the <code>Cache</code> as <code><a href="http://goo.gl/3TobQS">Promise</a></code>s for <code>Response</code> instances, the objects stored are <code><a href="http://goo.gl/3TobQS">Promise</a></code>s for <code>OpaqueResponse</code> instances. <code>OpaqueResponse</code> provides a much less expressive API than <code>Response</code>; the bodies and headers cannot be read or set, nor many of the other aspects of their content inspected. They can be passed to <code>respondWith()</code> and <code>forwardTo()</code> in the same manner as <code>Response</code>s, but cannot be meaningfully created programmatically. These limitations are necessary to preserve the security invariants of the platform. Allowing <code>Cache</code>s to store them allows applications to avoid re-architecting in most cases.</p>
  </spec-section>
</spec-clause>

<spec-clause id="storage-considerations">
  <h1 id="h1-storage-considerations">Storage Considerations</h1>

  <p class="note">Service Workers should take a dependency on <a href="http://www.w3.org/TR/quota-api/">Quota Management</a> in preparation for an extension event that communicates storage pressure and pre-eviction information to the application.</p>
</spec-clause>

<spec-clause id="extensibility">
  <h1 id="h1-extensibility">Extensibility</h1>

  <p class="note">The expectation is that service workers are meant to be extensible from other specifications. As of now, <a href="https://github.com/slightlyoff/BackgroundSync">BackgroundSync</a> event, <a href="http://www.w3.org/2012/sysapps/web-alarms/">TaskScheduler</a> and <a href="https://dvcs.w3.org/hg/push/raw-file/tip/index.html">Push API</a> would be the prime candidates and more will come. That said, we want to make sure that the future works won't be adding synchronous cruft, etc. This section will provide template text for how to extend the service workers.</p>
</spec-clause>

<spec-clause id="algorithms">
  <h1 id="h1-algorithms">Appendix A: Algorithms</h1>

  <p class="note">Underscored functions and attributes are UA-internal properties.</p>

  <spec-section id="registration-algorithm">
    <h1 id="h1-registration-algorithm">Registration</h1>

    <p>The <a href="#registration-algorithm">Service Worker Registration Algorithm</a> creates or updates a <a href="#registration-internal-interface">registration</a> for some amount of <a href="#url-scope">url scope</a>. If successful, a registration ties the provided <code>scriptUrl</code> to an <a href="http://goo.gl/56C6hc">origin</a> + <code>scope</code> pair which is subsequently consulted by the user for <a href="#scope-match-algorithm">navigation matching</a>.</p>

    <spec-algorithm>
    <dl>
      <dt>Input</dt>
        <dd><var>scriptUrl</var>, the URL of the script to register; a string</dd>
        <dd><var>scope</var>, a string representing a <a href="#path-expression">path expression</a> of <a href="#url-scope">url scope</a></dd>
      <dt>Output</dt>
        <dd><var>promise</var>, a <a href="http://goo.gl/3TobQS">promise</a> whose resolution indicates the success or failure of the algorithm</dd>
    </dl>
    <ol>
      <li>Let <var>promise</var> be a newly-created <a href="http://goo.gl/3TobQS">promise</a>.</li>
      <li>Return <var>promise</var>.</li>
      <li>Run the following steps asynchronously:
        <ol>
          <li>Let <var>scope</var> be <var>scope</var> resolved against the document url.</li>
          <li>Let <var>scriptUrl</var> be <var>scriptUrl</var> resolved against the document url.</li>
          <li>If the scheme of the document url is not <code>https</code>, then: <small>// Browsers may ignore this rule for development purposes only.</small>
            <ol>
              <li>Reject <var>promise</var> with a new <code>SecurityError</code>.</li>
              <li>Abort these steps.</li>
            </ol>
          </li>
          <li>If the origin of <var>scriptUrl</var> does not match the document's origin, then:
            <ol>
              <li>Reject <var>promise</var> with a new <code>SecurityError</code>.</li>
              <li>Abort these steps.</li>
            </ol>
          </li>
          <li>If the origin of <var>scope</var> does not match the document's origin, then:
            <ol>
              <li>Reject <var>promise</var> with a new <code>SecurityError</code>.</li>
              <li>Abort these steps.</li>
            </ol>
          </li>
          <li>Let <var>serviceWorkerRegistration</var> be the result of running the <a href="#get-registration-algorithm">_GetRegistration algorithm</a> passing <var>scope</var> as the argument.</li>

          <li>If <var>serviceWorkerRegistration</var> is not null, then:
            <ol>
              <li>Set <var>serviceWorkerRegistration.uninstalling</var> to false.</li>
              <li>If <var>scriptUrl</var> is equal to <var>serviceWorkerRegistration.scriptUrl</var>, then:
                <ol>
                  <li>If <var>serviceWorkerRegistration.updatePromise</var> is not null, then:
                    <ol>
                      <li>Resolve <var>promise</var> with <var>serviceWorkerRegistration.updatePromise</var>.</li>
                      <li>Abort these steps.</li>
                    </ol>
                  </li>
                  <li>Let newestWorker be <a href="#get-newest-worker-algorithm">_GetNewestWorker</a>(<var>serviceWorkerRegistration</var>).</li>
                  <li>If newestWorker is not null, then:
                    <ol>
                      <li>Resolve promise with <var>newestWorker</var>.</li>
                      <li>Abort these steps.</li>
                    </ol>
                  </li>
                </ol>
              </li>
            </ol>
          </li>
          <li>If <var>serviceWorkerRegistration</var> is null, then:
            <ol>
              <li>Let <var>serviceWorkerRegistration</var> be a newly-created <a href="#registration-internal-interface">_ServiceWorkerRegistration</a> object.</li>
              <li>Set <var>serviceWorkerRegistration</var> to the value of key <var>scope</var> in <a href="#scope-to-service-worker-registration-map-internal-interface">_ScopeToServiceWorkerRegistrationMap</a>.</li>
              <li>Set <var>serviceWorkerRegistration</var>.<var>scope</var> to <var>scope</var>.</li>
              <li>Set <var>serviceWorkerRegistration</var>.<var>uninstalling</var> to false.</li>
            </ol>
          </li>
          <li>Set <var>serviceWorkerRegistration</var>.<var>scriptUrl</var> to <var>scriptUrl</var>.</li>
          <li>Resolve <var>promise</var> with the result of running the <a href="#update-algorithm">_Update algorithm</a> passing <var>serviceWorkerRegistration</var> as the argument.</li>
        </ol>
      </li>
    </ol>
    </spec-algorithm>
  </spec-section>

  <spec-section id="update-algorithm">
    <h1 id="h1-update-algorithm">_Update</h1>

    <p>The <a href="#update-algorithm">Service Worker _Update Algorithm</a>, run by the user agent, upgrades an <a href="#successfully-installed">installed</a> Service Worker to a new version for the same <a href="#url-scope">url scope</a>. If successful, the newly <a href="#successfully-installed">installed</a> Service Worker becomes the <a href="#worker-in-waiting">Service Worker in waiting</a> which becomes the <a href="#navigator-service-worker-current">active</a> Service Worker as soon as all the documents served by the previous Service Worker are closed. When scheduling a fetch of a new version, the user agent should honor the HTTP cache headers with the upper limit of 24 hours:</p>

  <!--
  #FIXME: (Checkpoint) This is a platform implmentation not exposing APIs to userland. As such, Promise is not used for its output.
  -->
    <spec-algorithm>
    <dl>
      <dt>Input</dt>
        <dd><var>serviceWorkerRegistration</var>, a record of the internal map structure keyed by a <a href="#url-scope">relative URL pattern</a>, <var>scope</var>, with the value of properties, <var>scriptUrl</var>, <var>installingWorker</var>, <var>waitingWorker</var>, <var>currentWorker</var> and <var>updatePromise</var>; a <dfn id="registration-internal-interface">_ServiceWorkerRegistration</dfn> object</dd>
      <dt>Output</dt>
        <dd><var>promise</var>, a <a href="http://goo.gl/3TobQS">promise</a> whose resolution indicates the success or failure of the algorithm</dd>
    </dl>
    <ol>
      <li>If <var>serviceWorkerRegistration</var>.<var>updatePromise</var> is not null, then:
        <ol>
          <li>Reject <var>serviceWorkerRegistration</var>.<var>updatePromise</var> with a new <code>AbortError</code>.</li>
          <li>The browser may abort in-flight requests, parsing or worker execution relating to <var>serviceWorkerRegistration</var>.<var>updatePromise</var>.</li>
        </ol>
      </li>
      <li>If <var>serviceWorkerRegistration</var>.<var>installingWorker</var> is not null, then:
        <ol>
          <li>Terminate <var>serviceWorkerRegistration</var>.<var>installingWorker</var>.</li>
          <li>Set <var>serviceWorkerRegistration</var>.<var>installingWorker</var>.<var>state</var> to <code>redundant</code>.</li>
          <li>Fire <code>statechange</code> event on <var>serviceWorkerRegistration</var>.<var>installingWorker</var>.</li>
          <li>Set <var>serviceWorkerRegistration</var>.<var>installingWorker</var> to null.</li>
          <li>The user agent may abort any in-flight requests triggered by <var>serviceWorkerRegistration</var>.<var>installingWorker</var>.</li>
        </ol>
      </li>
      <li>Let <var>promise</var> be a newly-created <a href="http://goo.gl/3TobQS">promise</a>.</li>
      <li>Set <var>serviceWorkerRegistration</var>.<var>updatePromise</var> to <var>promise</var>.</li>
      <li>Return <var>promise</var>.</li>
      <li>Run the following steps asynchronously:
        <ol>
          <li>Perform a fetch of <var>serviceWorkerRegistration</var>.<var>scriptUrl</var>, forcing a network fetch if cached entry is greater than 1 day old.</li>
          <li>If <var>promise</var> has been rejected (eg, another registration has aborted it), then:
            <ol>
              <li>Set <var>serviceWorkerRegistration</var>.<var>updatePromise</var> to null.</li>
              <li>Abort these steps.</li>
            </ol>
          </li>
          <li>Else if fetching the script fails due to the server returning a 4xx response or a 5xx response, or there is a DNS error, or the connection times out, then:
            <ol>
              <li>Reject <var>promise</var> with a new <code>NetworkError</code>.</li>
              <li>Set <var>serviceWorkerRegistration</var>.<var>updatePromise</var> to null.</li>
              <li>Abort these steps.</li>
            </ol>
          </li>
          <li>Else if the server returned a redirect, then:
            <ol>
              <li>Reject <var>promise</var> with a new <code>SecurityError</code>.</li>
              <li>Set <var>serviceWorkerRegistration</var>.<var>updatePromise</var> to null.</li>
              <li>Abort these steps.</li>
            </ol>
          </li>
          <li>Let <var>fetchedScript</var> be the fetched script.</li>
          <li>Let <var>newestWorker</var> be <code>_GetNewestWorker</code>(<var>serviceWorkerRegistration</var>).</li>
          <li>If <var>newestWorker</var> is not null, and <var>newestWorker</var>.<var>url</var> is equal to <var>serviceWorkerRegistration</var>.<var>scriptUrl</var> and <var>fetchedScript</var> is a byte-for-byte match with the script of <var>newestWorker</var>, then:
            <ol>
              <li>Resolve <var>promise</var> with <var>newestWorker</var>.</li>
              <li>Set <var>serviceWorkerRegistration</var>.<var>updatePromise</var> to null.</li>
              <li>Abort these steps.</li>
            </ol>
          </li>
          <li>Else,
            <ol>
              <li>Let <var>serviceWorker</var> be a newly-created <a href="#service-worker-interface">ServiceWorker</a> object, using <var>fetchedScript</var>.</li>
              <li>If <var>promise</var> has been rejected (e.g, another registration has aborted it), then:
                <ol>
                  <li>Set <var>serviceWorkerRegistration</var>.<var>updatePromise</var> to null.</li>
                  <li>Abort these steps.</li>
                </ol>
              </li>
              <li>If <var>serviceWorker</var> fails to start up, due to parse errors or uncaught errors, then:
                <ol>
                  <li>Reject <var>promise</var> with the error.</li>
                  <li>Set <var>serviceWorkerRegistration</var>.<var>updatePromise</var> to null.</li>
                  <li>Abort these steps.</li>
                </ol>
              </li>
              <li>Resolve <var>promise</var> with <var>serviceWorker</var>.</li>
              <li>Set <var>serviceWorkerRegistration</var>.<var>updatePromise</var> to null.</li>
              <li>Queue a task to invoke <a href="#installation-algorithm">_Installation algorithm</a> with <var>serviceWorkerRegistration</var> and <var>serviceWorker</var> as its arguments.</li>
            </ol>
          </li>
        </ol>
      </li>
    </ol>
    </spec-algorithm>
  </spec-section>

  <spec-section id="soft-update-algorithm">
    <h1 id="h1-soft-update-algorithm">_SoftUpdate</h1>

    <p>The browser may call this as often as it likes to check for updates.</p>

    <spec-algorithm>
    <dl>
      <dt>Input</dt>
        <dd><var>serviceWorkerRegistration</var>, a record of the internal map structure keyed by a <a href="#url-scope">relative URL pattern</a>, <var>scope</var>, with the value of properties, <var>scriptUrl</var>, <var>installingWorker</var>, <var>waitingWorker</var>, <var>currentWorker</var> and <var>updatePromise</var>; a <a href="#registration-internal-interface">_ServiceWorkerRegistration</a> object</dd>
      <dt>Output</dt>
        <dd>None</dd>
    </dl>
    <ol>
      <li>If <var>serviceWorkerRegistration</var>.<var>uninstalling</var> is true, then:
        <ol>
          <li>Abort these steps.</li>
        </ol>
      </li>
      <li>If <var>serviceWorkerRegistration</var>.<var>updatePromise</var> is not null, then:
        <ol>
          <li>Abort these steps.</li>
        </ol>
      </li>
      <li>If <var>serviceWorkerRegistration</var>.<var>installingWorker</var> is not null, then:
        <ol>
          <li>Abort these steps.</li>
        </ol>
      </li>
      <li>Queue a task to invoke <a href="#update-algorithm">_Update algorithm</a> with <var>serviceWorkerRegistration</var> as its argument.</li>
    </ol>
    </spec-algorithm>
  </spec-section>

  <spec-section id="installation-algorithm">
    <h1 id="h1-installation-algorithm">_Installation</h1>

    <spec-algorithm>
    <dl>
      <dt>Input</dt>
        <dd><var>serviceWorkerRegistration</var>, a record of the internal map structure keyed by a <a href="#url-scope">relative URL pattern</a>, <var>scope</var>, with the value of properties, <var>scriptUrl</var>, <var>installingWorker</var>, <var>waitingWorker</var>, <var>currentWorker</var> and <var>updatePromise</var>; a <a href="#registration-internal-interface">_ServiceWorkerRegistration</a> object</dd>
        <dd><var>serviceWorker</var>, the object representing the document-side view of a Service Worker; a <a href="#service-worker-interface">ServiceWorker</a> object</dd>
      <dt>Output</dt>
        <dd>None</dd>
    </dl>
    <ol>
      <li>Set <var>serviceWorkerRegistration</var>.<var>installingWorker</var> to <var>serviceWorker</var>.</li>
      <li>Set <var>serviceWorkerRegistration</var>.<var>installingWorker</var>.<var>state</var> to <code>installing</code>.</li>
      <li>Fire <code>install</code> event on the associated <a href="#service-worker-global-scope"><code>ServiceWorkerGlobalScope</code></a> object.</li>
      <li>Fire <code>updatefound</code> event on <code>navigator.serviceWorker</code> for all documents which match <var>serviceWorkerRegistration</var>.<var>scope</var>.</li>
      <li>If any handler called <code>waitUntil()</code>, then:
        <ol>
          <li>Extend this process until the associated promises settle.</li>
          <li>If the resulting promise rejects, then:
            <ol>
              <li>Set <var>serviceWorkerRegistration</var>.<var>installingWorker</var>.<var>state</var> to <code>redundant</code>.</li>
              <li>Fire <code>statechange</code> event on <var>serviceWorkerRegistration</var>.<var>installingWorker</var>.</li>
              <li>Set <var>serviceWorkerRegistration</var>.<var>installingWorker</var> to null.</li>
              <li>Abort these steps.</li>
            </ol>
          </li>
        </ol>
      </li>
      <li>If serviceWorkerRegistration.waitingWorker is not null, then:
        <ol>
          <li>Set <var>serviceWorkerRegistration</var>.<var>waitingWorker</var>.<var>state</var> to <code>redundant</code>.</li>
        </ol>
      </li>
      <li>Set <var>serviceWorkerRegistration.waitingWorker</var> to <var>serviceWorkerRegistration.installingWorker</var></li>
      <li>Set <var>serviceWorkerRegistration.installingWorker</var> to null</li>
      <li>Set <var>serviceWorkerRegistration</var>.<var>waitingWorker</var>.<var>state</var> to <code>installed</code>.</li>
      <li>Fire <code>statechange</code> event on <var>serviceWorkerRegistration</var>.<var>waitingWorker</var>.</li>
      <li>If any handler called <code>replace()</code>, then:
        <ol>
          <li>For each document matching <var>serviceWorkerRegistration</var>.<var>scope</var>:
            <ol>
              <li>Set <var>serviceWorkerRegistration</var> as the document's service worker registration.</li>
            </ol>
          </li>
          <li>Run <a href="#activation-algorithm">_Activation algorithm</a> passing <var>serviceWorkerRegistration</var> as the argument.</li>
          <li>Abort these steps.</li>
        </ol>
      </li>
      <li>If no document is using <var>serviceWorkerRegistration</var> as their service worker registration, then:
        <ol>
          <li>Queue a task to invoke <a href="#activation-algorithm">_Activation algorithm</a> with <var>serviceWorkerRegistration</var> as its argument.</li>
        </ol>
      </li>
    </ol>
    </spec-algorithm>
  </spec-section>

  <spec-section id="activation-algorithm">
    <h1 id="h1-activation-algorithm">_Activation</h1>

    <spec-algorithm>
    <dl>
      <dt>Input</dt>
        <dd><var>serviceWorkerRegistration</var>, a record of the internal map structure keyed by a <a href="#url-scope">relative URL pattern</a>, <var>scope</var>, with the value of properties, <var>scriptUrl</var>, <var>installingWorker</var>, <var>waitingWorker</var>, <var>currentWorker</var> and <var>updatePromise</var>; a <a href="#registration-internal-interface">_ServiceWorkerRegistration</a> object</dd>
      <dt>Output</dt>
        <dd>None</dd>
    </dl>
    <ol>
      <li>Let <var>activatingWorker</var> be <var>serviceWorkerRegistration</var>.<var>waitingWorker</var>.</li>
      <li>Let <var>exitingWorker</var> be <var>serviceWorkerRegistration</var>.<var>currentWorker</var>.</li>
      <li>If <var>exitingWorker</var> is not null, then:
        <ol>
          <li>Wait for <var>exitingWorker</var> to finish handling any in-progress requests.
          </li>
          <li>Terminate <var>exitingWorker</var>.</li>
          <li>Set <var>exitingWorker</var>.<var>state</var> to <code>redundant</code>.</li>
          <li>Fire <code>statechange</code> event on <var>exitingWorker</var>.</li>
        </ol>
      </li>
      <li>Set <var>serviceWorkerRegistration.currentWorker</var> to <var>activatingWorker</var>.</li>
      <li>Set <var>serviceWorkerRegistration</var>.<var>waitingWorker</var> to null.</li>
      <li>Set <var>serviceWorkerRegistration</var>.<var>currentWorker</var>.<var>state</var> to <code>activating</code>.</li>
      <li>Fire <code>statechange</code> event on <var>serviceWorkerRegistration</var>.<var>currentWorker</var>.</li>
      <li>Fire <code>currentchange</code> event on <var>navigator.serviceWorker</var> for all documents that have selected <var>serviceWorkerRegistration</var>.</li>
      <li>Fire <var>activate</var> event on the associated <a href="#service-worker-global-scope-interface"><code>ServiceWorkerGlobalScope</code></a> object.</li>
      <li>If any handler calls <code>waitUntil()</code>, then:
        <ol>
          <li>Extend this process until the associated promises settle.</li>
        </ol>
      </li>
      <li>Set <var>serviceWorkerRegistration</var>.<var>currentWorker</var>.<var>state</var> to <code>activated</code>.</li>
      <li>Fire <code>statechange</code> event on <var>serviceWorkerRegistration</var>.<var>currentWorker</var>.</li>
    </ol>
    </spec-algorithm>
  </spec-section>

  <spec-section id="on-navigation-request-algorithm">
    <h1 id="h1-on-navigation-request-algorithm">_OnNavigationRequest</h1>

    <spec-algorithm>
    <dl>
      <dt>Input</dt>
        <dd><var>request</var>, the object representing the request of fetching a resource; a <a href="#request-interface">Request</a> object</dd>
      <dt>Output</dt>
        <dd>None</dd>
    </dl>
    <ol>
      <li>If <var>request</var> is a force-refresh (shift+refresh), then:
        <ol>
          <li>Fetch the resource normally and abort these steps.</li>
        </ol>
      </li>
      <li>Let <var>parsedUrl</var> be the result of parsing <var>request</var>.<var>url</var>.</li>
      <li>Let <var>serviceWorkerRegistration</var> be the result of running <a href="#scope-match-algorithm">_ScopeMatch algorithm</a> passing <var>parsedUrl</var> as the argument.</li>
      <li>If <var>serviceWorkerRegistration</var> is null, then:
        <ol>
          <li>Fetch the resource normally and abort these steps.</li>
        </ol>
      </li>
      <li>Let <var>matchedServiceWorker</var> be <var>serviceWorkerRegistration</var>.<var>currentWorker</var>.</li>
      <li>If <var>matchedServiceWorker</var> is null, then:
        <ol>
          <li>Fetch the resource normally and abort these steps.</li>
        </ol>
      </li>
      <li>Document will now use <var>serviceWorkerRegistration</var> as its service worker registration.</li>
      <li>If <var>matchedServiceWorker</var>.<var>state</var> is <code>activating</code>, then:
        <ol>
          <li>Wait for <var>matchedServiceWorker</var>.<var>state</var> to become <code>activated</code>.</li>
        </ol>
      </li>
      <li>Fire <code>fetch</code> event on the associated <a href="#service-worker-global-scope-interface"><code>ServiceWorkerGlobalScope</code></a> object with a new FetchEvent object.</li>
      <li>If <code>respondWith()</code> was not called, then:
        <ol>
          <li>Fetch the resource normally.</li>
          <li>Queue a task to invoke <a href="#soft-update-algorithm">_SoftUpdate algorithm</a> with <var>serviceWorkerRegistration</var>as its argument.</li>
          <li>Abort these steps.</li>
        </ol>
      </li>
      <li>Let <var>responsePromise</var> be value passed into <code>respondWith()</code> casted to a <a href="http://goo.gl/3TobQS">promise</a>.</li>
      <li>Wait for <var>responsePromise</var> to settle.</li>
      <li>If <var>responsePromise</var> rejected, then:
        <ol>
          <li>Fail the resource load as if there had been a generic network error and abort these steps.</li>
        </ol>
      </li>
      <li>If <var>responsePromise</var> resolves to a <a href="#opaque-response-interface"><code>OpaqueResponse</code></a>, then:
        <ol>
          <li>Fail the resource load as if there had been a generic network error and abort these steps.</li>
        </ol>
      </li>
      <li>If <var>responsePromise</var> resolves to an <a href="#abstract-response-interface"><code>AbstractResponse</code></a>, then:
        <ol>
          <li>Serve the response.</li>
          <li>Queue a task to invoke <a href="#soft-update-algorithm">_SoftUpdate algorithm</a> with <var>serviceWorkerRegistration</var> as the argument.</li>
          <li>Abort these steps.</li>
        </ol>
      </li>
      <li>Fail the resource load as if there had been a generic network error and abort these steps.</li>
    </ol>
    </spec-algorithm>
  </spec-section>

  <spec-section id="on-resource-request-algorithm">
    <h1 id="h1-on-resource-request-algorithm">_OnResourceRequest</h1>

    <spec-algorithm>
    <dl>
      <dt>Input</dt>
        <dd><var>request</var>, the object representing the request of fetching a resource; a <a href="#request-interface">Request</a> object</dd>
      <dt>Output</dt>
        <dd>None</dd>
    </dl>
    <ol>
      <li>Let <var>serviceWorkerRegistration</var> be the registration used by this document.</li>
      <li>If <var>serviceWorkerRegistration</var> is null, then:
        <ol>
          <li>Fetch the resource normally and abort these steps.</li>
        </ol>
      </li>
      <li>Let <var>matchedServiceWorker</var> be <var>serviceWorkerRegistration</var>.<var>activeWorker</var>.</li>
      <li>If <var>matchedServiceWorker</var> is null, then:
        <ol>
          <li>Fetch the resource normally and abort these steps.</li>
        </ol>
      </li>
      <li>If <var>matchedServiceWorker</var>.<var>state</var> is <code>activating</code>, then:
        <ol>
          <li>Wait for <var>matchedServiceWorker</var>.<var>state</var> to become <code>activated</code>.</li>
        </ol>
      </li>
      <li>Fire <code>fetch</code> event on the associated <a href="#service-worker-global-scope-interface"><code>ServiceWorkerGlobalScope</code></a> object with a new <a href="#fetch-event-interface"><code>FetchEvent</code></a> object.</li>
      <li>If <code>respondWith()</code> was not called, then:
        <ol>
          <li>Fetch the resource normally and abort these steps.</li>
        </ol>
      </li>
      <li>Let <var>responsePromise</var> be value passed into <code>respondWith()</code> casted to a <a href="http://goo.gl/3TobQS">promise</a>.</li>
      <li>Wait for <var>responsePromise</var> to resolve.</li>
      <li>If <var>responsePromise</var> rejected, then:
        <ol>
          <li>Fail the resource load as if there had been a generic network error and abort these steps.</li>
        </ol>
      </li>
      <li>If <var>responsePromise</var> resolves to an <a href="#abstract-response-interface"><code>AbstractResponse</code></a>, then:
        <ol>
          <li>Serve the response and abort these steps.</li>
        </ol>
      </li>
      <li>Fail the resource load as if there had been a generic network error and abort these steps.</li>
    </ol>
    </spec-algorithm>
  </spec-section>

  <spec-section id="on-document-unload-algorithm">
    <h1 id="h1-on-document-unload-algorithm">_OnDocumentUnload</h1>

    <spec-algorithm>
    <dl>
    <dt>Input</dt>
        <dd><var>document</var>, the document using the given <a href="#registration-internal-interface">_ServiceWorkerReistration</a> object as its service worker registration; a <a href="http://www.w3.org/TR/dom/#document"><code>Document</code></a> object</dd>
    <dt>Output</dt>
        <dd>None</dd>
    </dl>
    <ol>
      <li>Let <var>serviceWorkerRegistration</var> be the registration used by <var>document</var>.</li>
      <li>If <var>serviceWorkerRegistration</var> is null, then:
        <ol>
          <li>Abort these steps.</li>
        </ol>
      </li>
      <li>If any other document is using <var>serviceWorkerRegistration</var> as their service worker registration, then:
        <ol>
          <li>Abort these steps.</li>
        </ol>
      </li>
      <li>If serviceWorkerRegistration.uninstalling is true, then:
        <ol>
          <li>Delete <var>serviceWorkerRegistration.scope</var> from <var>_ScopeToServiceWorkerRegistrationMap</var>.</li>
          <li>Abort these steps.</li>
        </ol>
      </li>
      <li>If <var>serviceWorkerRegistration.updatePromise</var> is null and <var>serviceWorkerRegistration.installingWorker</var> is null and <var>serviceWorkerRegistration.waitingWorker</var> is null and <var>serviceWorkerRegistration.currentWorker</var> is null, then:
        <ol>
          <li>Delete <var>serviceWorkerRegistration.scope</var> from <var>_ScopeToServiceWorkerRegistrationMap</var>.</li>
          <li>Abort these steps.</li>
        </ol>
      </li>
      <li>If <var>serviceWorkerRegistration</var>.<var>waitingWorker</var> is not null:
        <ol>
          <li>Run <a href="#activation-algorithm">_Activatation algorithm</a> with <var>serviceWorkerRegistration</var> at the argument.</li>
        </ol>
      </li>
    </ol>
    </spec-algorithm>
  </spec-section>

  <spec-section id="unregistration-algorithm">
    <h1 id="h1-unregistration-algorithm">Unregistration</h1>

    <spec-algorithm>
    <dl>
      <dt>Input</dt>
        <dd><var>scope</var>, a string representing a <a href="#path-expression">path expression</a> of <a href="#url-scope">url scope</a></dd>
      <dt>Output</dt>
        <dd><var>promise</var>, a <a href="http://goo.gl/3TobQS">promise</a> whose resolution indicates the success or failure of the algorithm</dd>
    </dl>
    <ol>
      <li>Let <var>promise</var> be a newly-created <a href="http://goo.gl/3TobQS">promise</a>.</li>
      <li>Return <var>promise</var>.</li>
      <li>Run the following steps asynchronously:
        <ol>
          <li>Let <var>scope</var> be scope resolved against the document url.</li>
          <li>If the origin of <var>scope</var> does not match the document's origin, then:
            <ol>
              <li>Reject <var>promise</var> with a new <code>SecurityError</code>.</li>
              <li>Abort these steps.</li>
            </ol>
          </li>
          <li>Let <var>serviceWorkerRegistration</var> be the result of running <a href="#get-registration-algorithm">_GetRegistration algorithm</a> passing <var>scope</var> as the argument.</li>
          <li>If <var>serviceWorkerRegistration</var> is null, then:
            <ol>
              <li>Resolve <var>promise</var>.</li>
              <li>Abort these steps.</li>
            </ol>
          </li>
          <li>Set <var>serviceWorkerRegistration</var>.<var>uninstalling</var> to true.</li>
          <li>If <var>serviceWorkerRegistration</var>.<var>updatePromise</var> is not null, then:
            <ol>
              <li>Reject <var>serviceWorkerRegistration</var>.<var>updatePromise</var> with a new <code>AbortError</code>.</li>
              <li>The browser may abort in-flight requests, parsing or worker execution relating to <var>serviceWorkerRegistration</var>.<var>updatePromise</var>.</li>
            </ol>
          </li>
          <li>If <var>serviceWorkerRegistration</var>.<var>installingWorker</var> is not null, then:
            <ol>
              <li>Terminate <var>serviceWorkerRegistration</var>.<var>installingWorker</var>.</li>
              <li>Set <var>serviceWorkerRegistration</var>.<var>installingWorker</var>.<var>state</var> to <code>redundant</code>.</li>
             <li>Fire <code>statechange</code> event on <var>serviceWorkerRegistration</var>.<var>installingWorker</var>.</li>
              <li>Set <var>serviceWorkerRegistration</var>.<var>installingWorker</var> to null.</li>
              <li>The user agent may abort in-flight requests triggered by <var>serviceWorkerRegistration</var>.<var>installingWorker</var>.</li>
            </ol>
          </li>
          <li>If <var>serviceWorkerRegistration</var>.<var>waitingWorker</var> is not null, then:
            <ol>
              <li>Set <var>serviceWorkerRegistration</var>.<var>waitingWorker</var>.<var>state</var> to <code>redundant</code>.</li>
              <li>Fire <code>statechange</code> event on <var>serviceWorkerRegistration</var>.<var>waitingWorker</var>.</li>
              <li>Set <var>serviceWorkerRegistration</var>.<var>waitingWorker</var> to null.</li>
            </ol>
          </li>
          <li>Resolve <var>promise</var>.</li>
          <li>If no document is using <var>serviceWorkerRegistration</var> as their service worker registration, then:
            <ol>
              <li>Delete <var>scope</var> from <var>_ScopeToServiceWorkerRegistrationMap</var></li>
            </ol>
          </li>
        </ol>
      </li>
    </ol>
    </spec-algorithm>
  </spec-section>

  <spec-section id="scope-match-algorithm">
    <h1 id="h1-scope-match-algorithm">_ScopeMatch</h1>

    <spec-algorithm>
    <dl>
      <dt>Input</dt>
        <dd><var>url</var>, a string representing a <a href="#url-scope">relative URL pattern</a>; a string</dd>
      <dt>Output</dt>
        <dd><var>serviceWorkerRegistration</var>, a record of the internal map structure keyed by a <a href="#url-scope">relative URL pattern</a>, <var>scope</var>, with the value of properties, <var>scriptUrl</var>, <var>installingWorker</var>, <var>waitingWorker</var>, <var>currentWorker</var> and <var>updatePromise</var>; a <a href="#registration-internal-interface">_ServiceWorkerRegistration</a> object</dd>
    </dl>
    <ol>
      <li>Let <var>matchingScope</var> be the longest key in <dfn id="scope-to-service-worker-registration-map-internal-interface">_ScopeToServiceWorkerRegistrationMap</dfn> that glob-matches <var>url</var>.</li>
      <li>Let <var>serviceWorkerRegistration</var> be the result of running <a href="#get-registration-algorithm">_GetRegistration algorithm</a> passing <var>matchingScope</var> as the argument.</li>
      <li>Return <var>serviceWorkerRegistration</var>.</li>
    </ol>
    </spec-algorithm>
  </spec-section>

  <spec-section id="get-registration-algorithm">
    <h1 id="h1-get-registration-algorithm">_GetRegistration</h1>

    <spec-algorithm>
    <dl>
      <dt>Input</dt>
        <dd><var>scope</var>, a string representing a <a href="#url-scope">relative URL pattern</a>; a string</dd>
      <dt>Output</dt>
        <dd><var>serviceWorkerRegistration</var>, a record of the internal map structure keyed by a <a href="#url-scope">relative URL pattern</a>, <var>scope</var>, with the value of properties, <var>scriptUrl</var>, <var>installingWorker</var>, <var>waitingWorker</var>, <var>currentWorker</var> and <var>updatePromise</var>; a <a href="#registration-internal-interface">_ServiceWorkerRegistration</a> object</dd>
    </dl>
    <ol>
      <li>If there is no record for <var>scope</var> in <a href="#scope-to-service-worker-registration-map-internal-interface">_ScopeToServiceWorkerRegistrationMap</a>, then return null.</li>
      <li>Let <var>serviceWorkerRegistration</var> be the record for <var>scope</var> in <a href="#scope-to-service-worker-registration-map-internal-interface">_ScopeToServiceWorkerRegistrationMap</a>.</li>
      <li>Return <var>serviceWorkerRegistration</var>.</li>
    </ol>
    </spec-algorithm>
  </spec-section>

  <spec-section id="get-newest-worker-algorithm">
    <h1 id="h1-get-newest-worker-algorithm">_GetNewestWorker</h1>

    <spec-algorithm>
    <dl>
      <dt>Input</dt>
        <dd><var>serviceWorkerRegistration</var>, a record of the internal map structure keyed by a <a href="#url-scope">relative URL pattern</a>, <var>scope</var>, with the value of properties, <var>scriptUrl</var>, <var>installingWorker</var>, <var>waitingWorker</var>, <var>currentWorker</var> and <var>updatePromise</var>; a <a href="#registration-internal-interface">_ServiceWorkerRegistration</a> object</dd>
      <dt>Output</dt>
        <dd><var>serviceWorker</var>, the object representing the document-side view of a Service Worker; a <a href="#service-worker-interface">ServiceWorker</a> object</dd>
    </dl>
    <ol>
      <li>Let <var>newestWorker</var> be null.</li>
      <li>If <var>serviceWorkerRegistration</var>.<var>installingWorker</var> is not null, then:
        <ol>
          <li>Set <var>newestWorker</var> to <var>serviceWorkerRegistration</var>.<var>installingWorker</var>.</li>
        </ol>
      </li>
      <li>Else if <var>serviceWorkerRegistration</var>.<var>waitingWorker</var> is not null, then:
        <ol>
          <li>Set <var>newestWorker</var> to <var>serviceWorkerRegistration</var>.<var>waitingWorker</var>.</li>
        </ol>
      </li>
      <li>Else if <var>serviceWorkerRegistration</var>.<var>currentWorker</var> is not null, then:
        <ol>
          <li>Set <var>newestWorker</var> to <var>serviceWorkerRegistration</var>.<var>currentWorker</var>.</li>
        </ol>
      </li>
      <li>Return <var>newestWorker</var>.</li>
    </ol>
    </spec-algorithm>
</spec-section>

</spec-clause>

<spec-clause id="acknowledgements">
  <h1 id="h1-acknowledgements">Acknowledgements</h1>
  <!-- FIXME: INCOMPLETE!! Please add collaborators below. -->

  <p>Jake Archibald is a ghost-author of this document. The best instincts in the design are his. He similarly shaped many of the details through discussion and experimentation. The bits which are not his (but which are good) owe everything to his experience, persistence, and focus on enabling web developers. He embodies a hopeful example for developers in shaping browser efforts to more directly address real-world pain points. If Service Workers solve "offline for the web", the credit is due him.</p>

  <p>Deep thanks go to Andrew Betts for organizing and hosting a small workshop of like-minded individuals including: Jake Archibald, Jackson Gabbard, Tobie Langel, Robin Berjon, Patrick Lauke, Christian Heilmann. From the clarity of the day's discussions and the use-cases outlined there, much has become possible. Further thanks to Andrew for raising consciousness about the offline problem. His organization of EdgeConf and inclusion of Offline as a persistent topic there has created many opportunities and connections that have enabled this work to progress.</p>

  <p>Anne van Kesteren has generously lent his encyclopedic knowledge of Web Platform arcana and standards development experience throught the development of the Service Worker. This specification would be incomplete without his previous work in describing the real-world behavior of URLs, HTTP Fetch, Promises, and DOM. Similarly, this specification would not be possible without Ian Hickson's rigorous Web Worker spec. Much thanks to him.</p>

  <p>In no particular order, deep gratitude for design guidance and discussion goes to: Jungkee Song, Alec Flett, David Barrett-Kahn, Aaron Boodman, Michael Nordman, Tom Ashworth, Kinuko Yasuda, Darin Fisher, Jonas Sicking, Jesús Leganés Combarro, Mark Christian, Dave Hermann, Yehuda Katz, François Remy, Ilya Grigorik, Will Chan, Domenic Denicola, Nikhil Marathe, Yves Lafon, Adam Barth, Greg Simon, and Devdatta Akhawe.</p>

  <p>Jason Weber, Chris Wilson, Paul Kinlan, Ehsan Akhgari, and Daniel Austin have provided valuable, well-timed feedback on requirements and the standardization process.</p>

  <p>The authors would also like to thank Dimitri Glazkov for his scripts and formatting tools which have been essential in the production of this specification. The authors are also grateful for his considerable guidance.</p>

  <p>Thanks also to Vivian Cromwell, Greg Simon, and Alex Komoroske for their considerable professional support.</p>
</spec-clause>
</body>
</html>
